package com.laguille.games.monopoly.commons.board;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.Validate;

import com.laguille.games.monopoly.commons.player.Player;
import com.laguille.games.monopoly.commons.property.Property;
import com.laguille.games.monopoly.commons.property.PropertyImpl;

public class BoardImpl implements Board {

	private final static int START_CASE = 0;
	
	private final List<Property> spaces;
	private final Map<Player, Property> playerPositionMap;
	
	protected BoardImpl(List<Property> spaces) {
		this.spaces = new ArrayList<Property>(spaces);
		this.playerPositionMap = new HashMap<Player, Property>();
	}
	
	public List<Property> getSpaces() {
		return Collections.unmodifiableList(spaces);
	}

	@Override
	public String toString() {
		return "BoardImpl [spaces=" + spaces + "]";
	}

	public Property getPlayerPosition(Player player) {
		Validate.notNull(player);
		
		if (!playerPositionMap.containsKey(player)) {
			insertNewPlayerOnBoard(player);
		}
		return playerPositionMap.get(player);
	}

	public void movePlayer(Player player, int numberOfCases) {
		Validate.notNull(player);
		Validate.isTrue(numberOfCases > 0);
		
		if (!playerPositionMap.containsKey(player)) {
			insertNewPlayerOnBoard(player);
		}
		int idxOldPosition = spaces.indexOf(playerPositionMap.get(player));
		Property newPosition = spaces.get((idxOldPosition + numberOfCases) % spaces.size());
		playerPositionMap.put(player, newPosition);
		
	}
	
	private void insertNewPlayerOnBoard(Player player) {
		this.playerPositionMap.put(player, spaces.get(START_CASE));
	}

	private static Board instance;
	public static Board getInstance() {
		if (instance == null) {
		
			instance = new BoardImpl(generatePropertys());
		}
		return instance;
	}
	
	protected static List<Property> generatePropertys() {
		List<Property> spaces = new ArrayList<Property>();
		spaces.add(new PropertyImpl("property1", 100, 50));
		spaces.add(new PropertyImpl("property2", 100, 50));
		spaces.add(new PropertyImpl("property3", 100, 50));
		return spaces;
	}
}
